package com.wman.learn

/**
 * @ProjectName: wman
 * @Package: com.wman.learn
 * @ClassName: test
 * @Description: java类作用描述
 * @Author: wman
 * @CreateDate: 2020/7/13 16:30
 * @UpdateUser: 更新者
 * @UpdateDate: 2020/7/13 16:30
 * @UpdateRemark: 更新说明
 * @Version: 1.0
 */

fun main() {
    val list: List<String> = listOf("apple", "pear", "banana", "shit")
    var result = list.maxBy { it.length }
    result = list.findMax { it.length }
    result = list.findMax { it }
}

fun plus(num1: Int, num2: Int): Int {
    return num1 + num2
}

/**
 * 函数类型, 语法结构 (String, Int) -> Unit
 */
fun num1Andnum2(num1: Int, num2: Int, operation: (Int, Int) -> Int): Int {
    return operation(num1, num2)
}

/**
 * 扩展函数
 */
fun String.capitalEnd(): String {
    val charArray = this.toCharArray();
    charArray[length - 1] = charArray[length - 1].toUpperCase()

    return String(charArray)
}

/**
 * lambda表达式
 * 语法结构： { 参数名1:类型, 参数名2:类型 -> 函数体}
 * 应用场景：
 *  1. 调用了一个Java方法，这个方法又接收了一个单抽象方法接口，入点击事件
 *  2. 高阶函数，函数参数lambda表达式传递
 */
fun lambda() {
    val list: List<String> = listOf("apple", "pear", "banana", "shit")
    //    var result:String ?= list.maxBy { it.length }!!
    //    推导过程
    val lambda = { fruit: String ->
        fruit.length
    }
    var result: String? = list.maxBy(lambda)
    /**
     * list.maxBy({fruit: String -> fruit.length})
     * 如果一个函数接收的最后一个参数是一个lambda表达式，可以把参数移到括号的外面 list.maxBy(){fruit: String -> fruit.length}
     * 如果一个函数只接收一个lambda表达式，可以把括号省略 list.maxBy{fruit: String -> fruit.length}
     * 由于Kotlin的类型推到机制，很多时候不用显示的声明变量的类型 list.maxBy{fruit -> fruit.length}
     * 如果lambda表达式只有一个参数，参数可以省略掉，改用it替代  list.maxBy{it.length}
     */

//    println("wman".capitalEnd())
}

/**
 * 高阶函数
 */
fun funcation() {
    var num1 = 10
    var num2 = 20
    /**
     * 高阶函数：函数为参数的三种传入方式
     */
    num1Andnum2(num1, num2, ::plus)
    num1Andnum2(num1, num2, fun(num1, num2): Int {
        return num1 + num2
    })
    num1Andnum2(num1, num2) { a, b ->
        a + b
    }
    /**
     * 使用实例
     * SharedPreferences.modify
     * list.maxBy
     */
}

fun <T, R : Comparable<R>> List<T>.findMax(block: (T) -> R): T? {
    if (isEmpty()) {
        return null
    }
    var maxElement = get(0)
    var maxVaule = block(maxElement)
    for (element in this) {
        var value = block(element)
        if (value > maxVaule) {
            maxElement = element
            maxVaule = value
        }
    }

    return maxElement
}